#include <bits/stdc++.h>
#include <time.h>
using namespace std;

typedef struct mystruct {
	int i;
	int num;
}MS;

bool cmp(MS a, MS b) {
	return a.num > b.num;
}
int main(int argc, char **argv) {
    FILE *p1, *p2;
    int src, dst;
    int vertex_num, edge_num, my_edge_num = 0;
    int edge_off_l, edge_off_r;
    
    clock_t start, finish;
    double runtime_overhead;
	
    //input graph
    if (argc != 6) {
        cout << "Usage parameter: (offset file, info file, output file, bram_num, pipe_num)" << endl;
        exit (-1);
    }
    int partition_num = atoi(argv[4]);
    int pipe_num = atoi(argv[5]);

    //cout << "partition_num = " << partition_num << endl;
    //cout << "pipe_num = " << pipe_num << endl;

	if ((p1 = fopen(argv[1], "r")) == NULL) {
        cout << "no input file 1" << endl;
        exit (-1);
    }
    if ((p2 = fopen(argv[2], "r")) == NULL) {
        cout << "on input file 2" << endl;
        exit (-1);
    }

    fscanf(p1, "%d %d", &vertex_num, &edge_off_l);
    fscanf(p2, "%d", &edge_num);
    vector<int> *graph = (vector<int> *) calloc (vertex_num, sizeof(vector<int>));

    for (int i = 0; i < vertex_num ;++ i) {
        fscanf(p1, "%d", &edge_off_r);
        for (int j = edge_off_l; j < edge_off_r; ++ j) {
            fscanf(p2, "%d", &dst);
            graph[i].push_back(dst);
        }
        edge_off_l = edge_off_r;
    }
    fclose(p1);
    fclose(p2);

    //cout << "input file finished" << endl;

    if ((p1 = fopen(argv[3], "w")) == NULL) {
        cout << "no output file 1" << endl;
        exit (-1);
    }
    
    //fprintf(p1, "%d\n", edge_num);
    queue<int> tmp_edge[partition_num];
    int now_partition_id = 0;
	MS tmp_edge_now[partition_num];
    start = clock();
    for (int i = 0; i < vertex_num/10000; ++ i) {
        vector<int>::iterator it;
        int tmp_edge_num = 0;
        for (it = graph[i].begin(); it != graph[i].end(); ++ it) {
            tmp_edge[(*it) % partition_num].push(*it);
            tmp_edge_num ++;
        }
        /*
		for (int j = 0; j < partition_num; ++ j) {
			tmp_edge_now[j].i = j;
			tmp_edge_now[j].num = tmp_edge[j].size();
		}

        int edge_j = 0;
		for (; edge_j < tmp_edge_num; edge_j += pipe_num) {
			sort(tmp_edge_now, tmp_edge_now + partition_num, cmp);
			if (tmp_edge_now[pipe_num - 1].num == 0) break;
			for (int k = 0; k < pipe_num && k + edge_j < tmp_edge_num; ++ k) {
				//fprintf(p1, "%d\n", tmp_edge[tmp_edge_now[k].i].front());
				tmp_edge_now[k].num --;
				tmp_edge[tmp_edge_now[k].i].pop();

				my_edge_num ++;
			}
		}
        for (; edge_j < tmp_edge_num; ++ edge_j) {
            while (tmp_edge[now_partition_id].size() == 0) {
                now_partition_id = (now_partition_id + 1) % partition_num;
            }
            //fprintf(p1, "%d\n", tmp_edge[now_partition_id].front());
            tmp_edge[now_partition_id].pop();
			now_partition_id = (now_partition_id + 1) % partition_num;

			my_edge_num ++;
        }
	*/
	/*
        for (int j = 0; j < tmp_edge_num; ++ j) {
            while (tmp_edge[now_partition_id].size() == 0) {
                now_partition_id = (now_partition_id + 1) % PARTITION_NUM;
            }
            fprintf(p1, "%d\n", tmp_edge[now_partition_id].front());
            tmp_edge[now_partition_id].pop();
			now_partition_id = (now_partition_id + 1) % PARTITION_NUM;
        }
		*/
    }
    //cout << edge_num << " " << my_edge_num << endl;
    finish = clock();
    runtime_overhead = (finish - start)*1.0 / CLOCKS_PER_SEC;
    cout<<"[Results]: Runtime Overhead is "<< (runtime_overhead)*1000000000 <<"ns." <<endl;
    cout<< "INFO: Runtime overhead counted successfully."<<endl;
    fclose(p1);
}

